﻿using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using Support;
using SQLdbMySqlLib;
using SQLdbOracleLib;
using System.Reflection;

namespace PhotoBackupWS
{
    internal class Engine
    {
        ObjWSSession wsSess;
        MySQL sqlWSDB = new MySQL();
        string WSDBhost = "db4free.net";
        string WSDBusername = "pbuser";
        string WSDBpassword = "pbuser";
        string WSDBdatabase = "wsdb";

        public Object Act;
        public Type t;

        internal void ConnectToWsDB()
        {
            try
            {
                sqlWSDB.connect(WSDBhost, WSDBusername, WSDBpassword, WSDBdatabase);
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        internal void DisconnectFromWsDB()
        {
            sqlWSDB.disconnect();
        }

        internal ObjSession startSession()
        {
            Generator g = new Generator();
            string sessionID = g.Generate(30);
            byte[] KeyBytes = Aes.createKeyBytes(g.Generate(30), g.Generate(8));
            try
            {
                ConnectToWsDB();
                sqlWSDB.insertSession(sessionID, KeyBytes);
                DisconnectFromWsDB();
            }
            catch (Exception e)
            {
                throw e;
            }
            ObjSession sess = new ObjSession();
            sess.KeyBytes = KeyBytes;
            sess.SessionID = sessionID;
            return sess;
        }

        internal void sessionTimeoutRemover()
        {
            try
            {
                ConnectToWsDB();
                sqlWSDB.removeExpiredSessions();
                DisconnectFromWsDB();
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        internal ObjWSUser getUser(string userName)
        {
            try
            {
                ConnectToWsDB();
                DataSet dataSet = sqlWSDB.getUser(userName);
                ObjWSUser wsUser = new ObjWSUser();
                wsUser.Password = (string)dataSet.Tables[0].Rows[0]["Password"];
                wsUser.DbType = (string)dataSet.Tables[0].Rows[0]["DBtype"];
                wsUser.DbHost = (string)dataSet.Tables[0].Rows[0]["DBurl"];
                wsUser.DbUser = (string)dataSet.Tables[0].Rows[0]["DBuser"];
                wsUser.DbPassword = (string)dataSet.Tables[0].Rows[0]["DBpassword"];
                wsUser.DbName = (string)dataSet.Tables[0].Rows[0]["DBname"];
                DisconnectFromWsDB();
                return wsUser;
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        internal void insertDataObject(string sessionID, int type, int album, string eName, string eFileSize, byte[] eRawData)
        {
            try
            {
                wsSess = getSession(sessionID);
                ConnectToUserDB(wsSess);
                Object[] parsm = new Object[5];
                parsm[0] = type;
                parsm[1] = Int32.Parse(Aes.DecryptString(eFileSize, wsSess.KeyBytes));
                if (eRawData == null)
                {
                    parsm[2] = eRawData;
                }
                else
                {
                    parsm[2] = Aes.Decrypt(eRawData, wsSess.KeyBytes);
                }
                parsm[3] = Aes.DecryptString(eName, wsSess.KeyBytes);
                parsm[4] = album;
                t.GetMethod("insertDataObject", BindingFlags.Public | BindingFlags.Instance).Invoke(Act, parsm);
                DisconnectFromUserDB();
                updateLastAction(sessionID);
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        internal bool login(string userName, string sessionID, string ePassword)
        {
            //try
            //{
                ObjWSUser wsUser = getUser(userName);
                wsSess = getSession(sessionID);
                string dPassword = Aes.DecryptString(ePassword, wsSess.KeyBytes);
                if (dPassword.Equals(wsUser.Password))
                {
                    updateSession(wsUser, sessionID);
                    validateUserDbTables(sessionID);
                    return true;
                }
                else
                {
                    return false;
                }
            /*}
            catch (Exception e)
            {
                throw e;
            }*/
        }

        internal void updateSession(ObjWSUser wsUser, string sessionID)
        {
            try
            {
                ConnectToWsDB();
                sqlWSDB.updateSession(sessionID, wsUser.DbType, wsUser.DbHost, wsUser.DbUser, wsUser.DbPassword, wsUser.DbName);
                DisconnectFromWsDB();
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        internal ObjData getDataObject(string sessionID, int objectID)
        {
            try
            {
                wsSess = getSession(sessionID);
                ConnectToUserDB(wsSess);
                ObjData dataObj = new ObjData();

                Object[] parsm = new Object[1];
                parsm[0] = objectID;
                DataSet dataSet = (DataSet)t.GetMethod("getDataObject", BindingFlags.Public | BindingFlags.Instance).Invoke(Act, parsm);
                if (Convert.ToInt32(dataSet.Tables[0].Rows[0]["Type"]) == 0)
                {
                    DataSet dataSetContent = (DataSet)t.GetMethod("getAlbumContent", BindingFlags.Public | BindingFlags.Instance).Invoke(Act, parsm);
                    ObjContent[] objCont = new ObjContent[dataSetContent.Tables[0].Rows.Count];
                    int i = 0;
                    foreach (DataRow row in dataSetContent.Tables[0].Rows)
                    {
                        objCont[i] = new ObjContent();
                        objCont[i].EId = Aes.EncryptString(row["ID"] + "", wsSess.KeyBytes);
                        objCont[i].EName = Aes.EncryptString(row["Name"] + "", wsSess.KeyBytes);
                        objCont[i].EType = Aes.EncryptString(row["Type"] + "", wsSess.KeyBytes);
                        i++;
                    }
                    dataObj.ContentObj = objCont;
                }
                else
                {
                    dataObj.EFileSize = Aes.EncryptString(dataSet.Tables[0].Rows[0]["FileSize"] + "", wsSess.KeyBytes);
                    dataObj.EData = Aes.Encrypt((byte[])dataSet.Tables[0].Rows[0]["Data"], wsSess.KeyBytes);
                }
                dataObj.EName = Aes.EncryptString(dataSet.Tables[0].Rows[0]["Name"] + "", wsSess.KeyBytes);
                DisconnectFromUserDB();
                updateLastAction(sessionID);
                return dataObj;
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        internal void updateLastAction(string sessionID)
        {
            try
            {
                ConnectToWsDB();
                sqlWSDB.updateTimestamp(sessionID);
                DisconnectFromWsDB();
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        internal ObjWSSession getSession(string sessionID)
        {

            try
            {
                updateLastAction(sessionID);
                ConnectToWsDB();
                DataSet dataSet = sqlWSDB.getSession(sessionID);
                wsSess = new ObjWSSession();

                foreach (DataRow r in dataSet.Tables[0].Rows)
                {
                    wsSess.KeyBytes = (byte[])r["KeyBytes"];

                    wsSess.DbType = r["DBtype"] + "";
                    wsSess.DbHost = r["DBurl"] + "";
                    wsSess.DbUser = r["DBuser"] + "";
                    wsSess.DbPassword = r["DBpassword"] + "";
                    wsSess.DbName = r["DBname"] + "";


                }
                DisconnectFromWsDB();
                if (wsSess.DbType.Equals("") == false)
                {
                    GetSqlType(wsSess);
                }
                return wsSess;
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        internal void ConnectToUserDB(ObjWSSession wsSess)
        {
            Object[] parsm = new Object[4];
            parsm[0] = wsSess.DbHost;
            parsm[1] = wsSess.DbUser;
            parsm[2] = wsSess.DbPassword;
            parsm[3] = wsSess.DbName;
            t.GetMethod("connect", BindingFlags.Public | BindingFlags.Instance).Invoke(Act, parsm);
        }

        internal void DisconnectFromUserDB()
        {
            t.GetMethod("disconnect", BindingFlags.Public | BindingFlags.Instance).Invoke(Act, null);
        }

        internal void GetSqlType(ObjWSSession wsSess)
        {
            string DBtype = wsSess.DbType;
            switch (DBtype)
            {
                case "mysql":
                    t = typeof(MySQL);
                    break;

                case "oracle":
                    t = typeof(Oracle);
                    break;
                default:
                    break;
            }
            Act = Activator.CreateInstance(t);
        }

        internal string testMethod()
        {
            t = typeof(MySQL);
            Act = Activator.CreateInstance(t);
            Object[] parsm = new Object[4];
            parsm[0] = "db4free.net";
            parsm[1] = "pbuser";
            parsm[2] = "pbuser";
            parsm[3] = "wsdb";
            string retur = (string)t.GetMethod("connect2", BindingFlags.Public | BindingFlags.Instance).Invoke(Act, parsm);
            return retur;
        }

        internal void CreatePictureTable(ObjWSSession wsSess)
        {
            ConnectToUserDB(wsSess);
            t.GetMethod("createUserTable", BindingFlags.Public | BindingFlags.Instance).Invoke(Act, null);
            DisconnectFromUserDB();
        }

        internal bool deleteDataObject(string sessionID, string eObjID)
        {
            try
            {
                wsSess = getSession(sessionID);
                ConnectToUserDB(wsSess);
                int objectID = Int32.Parse(Aes.DecryptString(eObjID, wsSess.KeyBytes));
                Object[] parsm = new Object[1];
                parsm[0] = objectID;

                DataSet dataSet = (DataSet)t.GetMethod("getDataObject", BindingFlags.Public | BindingFlags.Instance).Invoke(Act, parsm);
                if (Int32.Parse(dataSet.Tables[0].Rows[0]["Type"] + "") == 0)
                {
                    //album
                    DataSet dataSet2 = (DataSet)t.GetMethod("getAlbumContent", BindingFlags.Public | BindingFlags.Instance).Invoke(Act, parsm);
                    if (dataSet2.Tables[0].Rows.Count == 0)
                    {
                        t.GetMethod("deleteDataObject", BindingFlags.Public | BindingFlags.Instance).Invoke(Act, parsm);
                        DisconnectFromUserDB();
                        return true;
                    }
                    else
                    {
                        DisconnectFromUserDB();
                        return false;
                    }
                }
                else
                {
                    t.GetMethod("deleteDataObject", BindingFlags.Public | BindingFlags.Instance).Invoke(Act, parsm);
                    DisconnectFromUserDB();
                    return true;
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }



        internal bool deleteAlbumContent(string sessionID, string eAlbumID)
        {
            try
            {
                wsSess = getSession(sessionID);
                ConnectToUserDB(wsSess);
                int albumID = Int32.Parse(Aes.DecryptString(eAlbumID, wsSess.KeyBytes));
                Object[] parsm = new Object[1];
                parsm[0] = albumID;


                DataSet dataSet = (DataSet)t.GetMethod("getAlbumContent", BindingFlags.Public | BindingFlags.Instance).Invoke(Act, parsm);
                if (dataSet.Tables[0].Rows.Count == 0)
                {
                    DisconnectFromUserDB();
                    return true;
                }
                else
                {
                    bool albumExists = false;
                    foreach (DataRow r in dataSet.Tables[0].Rows)
                    {
                        if (Int32.Parse(r["Type"] + "") == 0)
                        {
                            albumExists = true;
                            break;
                        }
                    }
                    if (albumExists)
                    {
                        DisconnectFromUserDB();
                        return false;
                    }
                    else
                    {
                        t.GetMethod("deleteAlbumContent", BindingFlags.Public | BindingFlags.Instance).Invoke(Act, parsm);
                        DisconnectFromUserDB();
                        return true;
                    }
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        internal void changeDataObjectName(string sessionID, string eObjectID, string eNewName)
        {
            try
            {
                wsSess = getSession(sessionID);
                ConnectToUserDB(wsSess);
                Object[] parsm = new Object[2];
                parsm[0] = Int32.Parse(Aes.DecryptString(eObjectID, wsSess.KeyBytes));
                parsm[1] = Aes.DecryptString(eNewName, wsSess.KeyBytes);
                t.GetMethod("updateName", BindingFlags.Public | BindingFlags.Instance).Invoke(Act, parsm);
                DisconnectFromUserDB();
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        internal void changeDataObjectAlbum(string sessionID, string eObjectID, string eNewAlbum)
        {
            try
            {
                wsSess = getSession(sessionID);
                ConnectToUserDB(wsSess);
                Object[] parsm = new Object[2];
                parsm[0] = Int32.Parse(Aes.DecryptString(eObjectID, wsSess.KeyBytes));
                parsm[1] = Int32.Parse(Aes.DecryptString(eNewAlbum, wsSess.KeyBytes));
                t.GetMethod("updateLocation", BindingFlags.Public | BindingFlags.Instance).Invoke(Act, parsm);
                DisconnectFromUserDB();
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        internal void validateUserDbTables(string sessionID)
        {
            wsSess = getSession(sessionID);
            ConnectToUserDB(wsSess);
            Object[] parsm = new Object[1];
            parsm[0] = wsSess.DbName;
            DataSet dataSet = (DataSet)t.GetMethod("checkPictureTableExistance", BindingFlags.Public | BindingFlags.Instance).Invoke(Act, parsm);
            if (dataSet.Tables[0].Rows.Count == 0)
            {
                t.GetMethod("createUserTable", BindingFlags.Public | BindingFlags.Instance).Invoke(Act, null);
                //t.GetMethod("createRoot", BindingFlags.Public | BindingFlags.Instance).Invoke(Act,null);
            }
            DisconnectFromUserDB();
        }
    }
}
